package com.recursiveflow.openplatform.view 
{
    import com.gskinner.motion.GTween;
    import com.gu.tagbrowser.assets.ArticleLabel;
    import com.guardian.apis.content.model.ContentType;
    import com.guardian.apis.content.model.Item;
    import com.guardian.apis.content.model.ItemList;

    import flash.display.Sprite;
    import flash.events.MouseEvent;
    import flash.text.TextFieldAutoSize;
    import flash.utils.Dictionary;

    /**
     * View object containing a vertically arranged list of search results.
     * 
     * Each result is rendered using an ArticleLabel asset and positioned according to its index.
     * 
     * Title and publication info fields are filled in (and sized) based on result item data.
     * 
     * Non-article items have special icons shown to their left (set according to their content type).
     * 
     * Dictionaries are used to store the relationships between result items and their corresponding labels.
     * 
     * Mouse listeners relay every label's rollover / rollout / click events to global handlers and also show / hide
     * the famed Guardian chevron as appropriate.
     * 
     * The maximum number of visible results is precalculated (according to the maximum visible height). 
     * 
     * @author Alastair Dant / Recursive Flow / 2009
     */
    public class ResultPanel extends Sprite 
    {
        private var panel : Sprite;
        private var items : Array;
        private var itemLabelMap : Dictionary;
        private var padding : Number;
        private var maxHeight : Number;
        private var labelItemMap : Dictionary;
        private var onRollover : Function;
        private var onRollout : Function;
        private var onClick : Function;
        private var selectedLabel : ArticleLabel;
        private var selectedItem : Item;

        public function ResultPanel(maxHeight:Number, padding:Number)
        {
            this.maxHeight = maxHeight;
            this.padding = padding;
            this.panel = new Sprite();
        }
        
        public function setHandlers(onRollover:Function, onRollout:Function, onClick:Function):void
        {
            this.onClick = onClick;
            this.onRollout = onRollout;
            this.onRollover = onRollover;
        }

        public function getMaxVisibleResults():Number
        {
            var rowHeight : Number = (new ArticleLabel()).height + padding;
            
            return Math.round(maxHeight / rowHeight);
        }
        
        public function show(itemList : ItemList) : void
        {
        	this.items = itemList.getAll();
        	this.itemLabelMap = new Dictionary(true);
        	this.labelItemMap = new Dictionary(true);
        	
        	for each (var item : Item in items) 
        	{
        		var label:ArticleLabel = new ArticleLabel();
        		
        		itemLabelMap[item.getId()] = label;
        		labelItemMap[label] = item;
                
                label.titleField.autoSize = TextFieldAutoSize.LEFT;
                label.titleField.htmlText = item.getHeadline();
                
                label.authorField.autoSize = TextFieldAutoSize.LEFT;
                label.authorField.htmlText = getBylineFor(item);
                
                label.chevrons.x = label.titleField.x + Math.max(label.titleField.width, label.authorField.width) + 10;
                label.chevrons.y -= 2;
                label.chevrons.visible = false;
                
                label.icon.gotoAndStop(getIconFrame(item));

                label.icon.visible = (label.icon.currentFrame != 1);

                label.y = numChildren * (label.height + padding);       
                
                label.buttonMode = true;
                label.mouseChildren = false;
                
                label.addEventListener(MouseEvent.CLICK, handleClick); 		
                label.addEventListener(MouseEvent.MOUSE_OVER, handleRollover); 		
                label.addEventListener(MouseEvent.MOUSE_OUT, handleRollout); 		
                
                reveal(label);
        	}
        }
        
        private function handleClick(event : MouseEvent) : void
        {
            setSelected(event.target as ArticleLabel);
            onClick(event);
        }

        private function handleRollout(event : MouseEvent) : void
        {
            (event.target as ArticleLabel).chevrons.visible = false;
            onRollout(event);
        }

        private function handleRollover(event : MouseEvent) : void
        {
            setSelected(event.target as ArticleLabel);
            
            this.selectedLabel.chevrons.visible = true;
            
            onRollover(event);
        }
        
        private function setSelected(label:ArticleLabel) : void
        {
        	this.selectedLabel = label;
        	this.selectedItem = labelItemMap[label] as Item;
        }

        private function getIconFrame(item : Item) : Object
        {
            switch (item.getType())
            {
            	case ContentType.GALLERY: 
            	   return "Gallery";
            	case ContentType.AUDIO: 
            	   return "Audio";
            	case ContentType.VIDEO: 
            	   return "Video";
            	case ContentType.INTERACTIVE: 
            	   return "Interactive";
            	default:   
            	   return 1;
            }
        }

        private function getBylineFor(item : Item) : String
        {
        	if (item.getByline() && item.getByline().length > 0)
        	{
        		return "by " + item.getByline() + ", " + item.getPublishedOn().toLocaleDateString();
        	}
        	else
        	{
        		return "published on " + item.getPublishedOn().toLocaleDateString();
        	}
        }

        private function reveal(label : ArticleLabel) : void
        {
        	var delay:Number = numChildren * 0.15;
        	var tween:GTween = new GTween(label, 0.5, { x: 2*padding, alpha: 1 }, { delay: delay, autoPlay: false });
        	
        	label.x = -label.width;
        	label.alpha = 0;
        	
        	addChild(label);
        	
        	tween.play();
        }

        public function clear() : void
		{
			for each (var item : Item in items) 
			{
				var label:ArticleLabel = itemLabelMap[item.getId()] as ArticleLabel;
				
				removeChild(label);
			}
			
			items = [];
        }
        
        public function getSelectedItem() : Item
        {
            return selectedItem;
        }
    }
}
